<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="chrome=1">

    

    <title>
      js运行机制 | 江月夜 
    </title>

    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    
      <meta name="author" content="江月夜">
    
    

    <meta name="description" content="为什么JavaScript是单线程JavaScript最大的特点就是单线程，也就是说，同一时间只能做一件事情，为什么不是多线程呢？这样不是能提高效率吗？JavaScript单线程，与它的用途有关，它是一门运行在浏览器上的脚本语言，主要通途是与用户互动，操作页面。如果是多线程的话就会出现很多复杂的同步问题。比如有俩个线程">
<meta name="keywords" content="前端">
<meta property="og:type" content="article">
<meta property="og:title" content="js运行机制 | 江月夜">
<meta property="og:url" content="http://yoursite.com/2018/10/11/operate/index.html">
<meta property="og:site_name" content="江月夜">
<meta property="og:description" content="为什么JavaScript是单线程JavaScript最大的特点就是单线程，也就是说，同一时间只能做一件事情，为什么不是多线程呢？这样不是能提高效率吗？JavaScript单线程，与它的用途有关，它是一门运行在浏览器上的脚本语言，主要通途是与用户互动，操作页面。如果是多线程的话就会出现很多复杂的同步问题。比如有俩个线程，一个线程操作在某个节点上添加内容，另一个线程在这个节点上删除内容。那浏览器以哪">
<meta property="og:locale" content="zh-CN">
<meta property="og:updated_time" content="2018-10-29T09:07:14.786Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="js运行机制 | 江月夜">
<meta name="twitter:description" content="为什么JavaScript是单线程JavaScript最大的特点就是单线程，也就是说，同一时间只能做一件事情，为什么不是多线程呢？这样不是能提高效率吗？JavaScript单线程，与它的用途有关，它是一门运行在浏览器上的脚本语言，主要通途是与用户互动，操作页面。如果是多线程的话就会出现很多复杂的同步问题。比如有俩个线程，一个线程操作在某个节点上添加内容，另一个线程在这个节点上删除内容。那浏览器以哪">
    
    
    
      <link rel="icon" type="image/x-icon" href="/favicon.png">
    
    <link rel="stylesheet" href="/css/uno.css">
    <link rel="stylesheet" href="/css/highlight.css">
    <link rel="stylesheet" href="/css/archive.css">
    <link rel="stylesheet" href="/css/china-social-icon.css">

</head>
<body>

    <span class="mobile btn-mobile-menu">
        <i class="icon icon-list btn-mobile-menu__icon"></i>
        <i class="icon icon-x-circle btn-mobile-close__icon hidden"></i>
    </span>

    

<header class="panel-cover panel-cover--collapsed">


  <div class="panel-main">

  
    <div class="panel-main__inner panel-inverted">
    <div class="panel-main__content">

        

        <h1 class="panel-cover__title panel-title"><a href="/" title="link to homepage">江月夜</a></h1>
        <hr class="panel-cover__divider" />

        
        <p class="panel-cover__description">
          腹有诗书气自华
        </p>
        <hr class="panel-cover__divider panel-cover__divider--secondary" />
        

        <div class="navigation-wrapper">

          <nav class="cover-navigation cover-navigation--primary">
            <ul class="navigation">

              
                
                <li class="navigation__item"><a href="/#blog" title="" class="blog-button">首页</a></li>
              
                
                <li class="navigation__item"><a href="/about" title="" class="">关于</a></li>
              
                
                <li class="navigation__item"><a href="/archive" title="" class="">归档</a></li>
              

            </ul>
          </nav>

          <!-- ----------------------------
To add a new social icon simply duplicate one of the list items from below
and change the class in the <i> tag to match the desired social network
and then add your link to the <a>. Here is a full list of social network
classes that you can use:

    icon-social-500px
    icon-social-behance
    icon-social-delicious
    icon-social-designer-news
    icon-social-deviant-art
    icon-social-digg
    icon-social-dribbble
    icon-social-facebook
    icon-social-flickr
    icon-social-forrst
    icon-social-foursquare
    icon-social-github
    icon-social-google-plus
    icon-social-hi5
    icon-social-instagram
    icon-social-lastfm
    icon-social-linkedin
    icon-social-medium
    icon-social-myspace
    icon-social-path
    icon-social-pinterest
    icon-social-rdio
    icon-social-reddit
    icon-social-skype
    icon-social-spotify
    icon-social-stack-overflow
    icon-social-steam
    icon-social-stumbleupon
    icon-social-treehouse
    icon-social-tumblr
    icon-social-twitter
    icon-social-vimeo
    icon-social-xbox
    icon-social-yelp
    icon-social-youtube
    icon-social-zerply
    icon-mail

-------------------------------->

<!-- add social info here -->



<nav class="cover-navigation navigation--social">
  <ul class="navigation">

    
      <!-- Github -->
      <li class="navigation__item">
        <a href="https://github.com/ajiu9" title="">
          <i class='icon icon-social-github'></i>
          <span class="label">GitHub</span>
        </a>
      </li>
    

    <!-- China social icon -->
    <!--
    
      <li class="navigation__item">
        <a href="" title="">
          <i class='icon cs-icon-douban'></i>
          <span class="label">Douban</span>
        </a>
      </li>

      <li class="navigation__item">
        <a href="" title="">
          <i class='icon cs-icon-weibo'></i>
          <span class="label">Weibo</span>
        </a>
      </li>

    -->



  </ul>
</nav>



        </div>

      </div>

    </div>

    <div class="panel-cover--overlay"></div>
  </div>
</header>

    <div class="content-wrapper">
        <div class="content-wrapper__inner entry">
            

<article class="post-container post-container--single">

  <header class="post-header">
    
    <h1 class="post-title">js运行机制</h1>

    

    <div class="post-meta">
      <time datetime="2018-10-11" class="post-meta__date date">2018-10-11</time> 

      <span class="post-meta__tags tags">

          
            <font class="categories">
            &#8226; 分类:
            <a class="categories-link" href="/categories/js/">js</a>
            </font>
          

          
             &#8226; 标签:
            <font class="tags">
              <a class="tags-link" href="/tags/前端/">前端</a>
            </font>
          

      </span>
    </div>
    
    

  </header>

  <section id="post-content" class="article-content post">
    <h4 id="为什么JavaScript是单线程"><a href="#为什么JavaScript是单线程" class="headerlink" title="为什么JavaScript是单线程"></a>为什么JavaScript是单线程</h4><p>JavaScript最大的特点就是单线程，也就是说，同一时间只能做一件事情，为什么不是多线程呢？这样不是能提高效率吗？<br>JavaScript单线程，与它的用途有关，它是一门运行在浏览器上的脚本语言，主要通途是与用户互动，操作页面。如果是多线程的话就会出现很多复杂的同步问题。比如有俩个线程，一个线程操作在某个节点上添加内容，另一个线程在这个节点上删除内容。那浏览器以哪个线程为准？<br>所以为了避免复杂性，JavaScript从设计开始就是单线程的。</p>
<h4 id="任务列队"><a href="#任务列队" class="headerlink" title="任务列队"></a>任务列队</h4><p>单线程意味着所有任务需要排队，前一个任务结束才会运行下一个任务。如果一个任务运行耗时很长，下一个就得等待着。<br>如果排队是因为运算量太大，CPU忙不过来，倒也算了。可很多时候CPU是闲着的，因为IO设备（输入输出设备）很慢（比如Ajax操作从网络读取数据），不得不等着结果出来，再往下执行。<br>JavaScript语言的设计者意识到，这时主线程完全可以不管IO设备，挂起处于等待中的任务，先运行排在后面的任务。等到IO设备返回了结果，再回过头，把挂起的任务继续执行下去。<br>于是，所有任务可以分成两种，一种是同步任务（synchronous），另一种是异步任务（asynchronous）。同步任务指的是，在主线程上排队执行的任务，只有前一个任务执行完毕，才能执行后一个任务；异步任务指的是，不进入主线程、而进入”任务队列”（task queue）的任务，只有”任务队列”通知主线程，某个异步任务可以执行了，该任务才会进入主线程执行。<br>具体来说，异步执行的运行机制如下。（同步执行也是如此，因为它可以被视为没有异步任务的异步执行。）</p>
<ul>
<li>（1）所有同步任务都在主线程上执行，形成一个执行栈（execution context stack）。</li>
<li>（2）主线程之外，还存在一个”任务队列”（task queue）。只要异步任务有了运行结果，就在”任务队列”之中放置一个事件。</li>
<li>（3）一旦”执行栈”中的所有同步任务执行完毕，系统就会读取”任务队列”，看看里面有哪些事件。那些对应的异步任务，于是结束等待状态，进入执行栈，开始执行。</li>
<li>（4）主线程不断重复上面的第三步。</li>
</ul>
<h4 id="事件和回调函数"><a href="#事件和回调函数" class="headerlink" title="事件和回调函数"></a>事件和回调函数</h4><p>“任务队列”是一个事件的队列（也可以理解成消息的队列），IO设备完成一项任务，就在”任务队列”中添加一个事件，表示相关的异步任务可以进入”执行栈”了。主线程读取”任务队列”，就是读取里面有哪些事件。</p>
<p>“任务队列”中的事件，除了IO设备的事件以外，还包括一些用户产生的事件（比如鼠标点击、页面滚动等等）。只要指定过回调函数，这些事件发生时就会进入”任务队列”，等待主线程读取。</p>
<p>所谓”回调函数”（callback），就是那些会被主线程挂起来的代码。异步任务必须指定回调函数，当主线程开始执行异步任务，就是执行对应的回调函数。</p>
<p>“任务队列”是一个先进先出的数据结构，排在前面的事件，优先被主线程读取。主线程的读取过程基本上是自动的，只要执行栈一清空，”任务队列”上第一位的事件就自动进入主线程。但是，由于存在后文提到的”定时器”功能，主线程首先要检查一下执行时间，某些事件只有到了规定的时间，才能返回主线程。</p>
<h4 id="Event-Loop"><a href="#Event-Loop" class="headerlink" title="Event Loop"></a>Event Loop</h4><p>主线程从”任务队列”中读取事件，这个过程是循环不断的，所以整个的这种运行机制又称为Event Loop（事件循环）。</p>
<h4 id="定时器"><a href="#定时器" class="headerlink" title="定时器"></a>定时器</h4><p>除了放置异步任务的事件，”任务队列”还可以放置定时事件，即指定某些代码在多少时间之后执行。这叫做”定时器”（timer）功能，也就是定时执行的代码。<br>定时器功能主要由setTimeout()和setInterval()这两个函数来完成，它们的内部运行机制完全一样，区别在于前者指定的代码是一次性执行，后者则为反复执行。以下主要讨论setTimeout()。<br>总之，setTimeout(fn,0)的含义是，指定某个任务在主线程最早可得的空闲时间执行，也就是说，尽可能早得执行。它在”任务队列”的尾部添加一个事件，因此要等到同步任务和”任务队列”现有的事件都处理完，才会得到执行。</p>
<p>HTML5标准规定了setTimeout()的第二个参数的最小值（最短间隔），不得低于4毫秒，如果低于这个值，就会自动增加。在此之前，老版本的浏览器都将最短间隔设为10毫秒。另外，对于那些DOM的变动（尤其是涉及页面重新渲染的部分），通常不会立即执行，而是每16毫秒执行一次。这时使用requestAnimationFrame()的效果要好于setTimeout()。</p>
<p>需要注意的是，setTimeout()只是将事件插入了”任务队列”，必须等到当前代码（执行栈）执行完，主线程才会去执行它指定的回调函数。要是当前代码耗时很长，有可能要等很久，所以并没有办法保证，回调函数一定会在setTimeout()指定的时间执行。</p>

  </section>

  <section class="post-comments">

   <!--PC和WAP自适应版-->
<div id="SOHUCS" sid="请将此处替换为配置SourceID的语句" ></div> 
<script type="text/javascript"> 
(function(){ 
var appid = 'cytl2q04G'; 
var conf = 'prod_c6e77c75d2d767714e129c11e500044d'; 
var width = window.innerWidth || document.documentElement.clientWidth; 
if (width < 960) { 
window.document.write('<script id="changyan_mobile_js" charset="utf-8" type="text/javascript" src="https://changyan.sohu.com/upload/mobile/wap-js/changyan_mobile.js?client_id=' + appid + '&conf=' + conf + '"><\/script>'); } else { var loadJs=function(d,a){var c=document.getElementsByTagName("head")[0]||document.head||document.documentElement;var b=document.createElement("script");b.setAttribute("type","text/javascript");b.setAttribute("charset","UTF-8");b.setAttribute("src",d);if(typeof a==="function"){if(window.attachEvent){b.onreadystatechange=function(){var e=b.readyState;if(e==="loaded"||e==="complete"){b.onreadystatechange=null;a()}}}else{b.onload=a}}c.appendChild(b)};loadJs("https://changyan.sohu.com/upload/changyan.js",function(){window.changyan.api.config({appid:appid,conf:conf})}); } })(); </script>
    
</section>


</article>


            <footer class="footer">

    <span class="footer__copyright">&copy; 2017 | 由<a href="https://hexo.io/">Hexo</a>| 主题<a href="https://github.com/someus/huno">Huno</a></span>
    
</footer>
        </div>
    </div>

    <!-- js files -->
    <script src="/js/jquery.min.js"></script>
    <script src="/js/main.js"></script>
    <script src="/js/scale.fix.js"></script>
    

    

    <script type="text/javascript" src="//cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
    <script type="text/javascript"> 
        $(document).ready(function(){
            MathJax.Hub.Config({ 
                tex2jax: {inlineMath: [['[latex]','[/latex]'], ['\\(','\\)']]} 
            });
        });
    </script>


    

    <script src="/js/awesome-toc.min.js"></script>
    <script>
        $(document).ready(function(){
            $.awesome_toc({
                overlay: true,
                contentId: "post-content",
            });
        });
    </script>


    
    
    <!--kill ie6 -->
<!--[if IE 6]>
  <script src="//letskillie6.googlecode.com/svn/trunk/2/zh_CN.js"></script>
<![endif]-->

</body>
</html>
